﻿using System;
using System.Collections;
using System.Linq;
using System.Text.RegularExpressions;
using System.Xml;
using System.Xml.Serialization;

namespace MediaBot.Entities
{
    public class MatchType
    {
        [XmlAttribute("context")]
        public string Context = string.Empty;

        [XmlAttribute("pattern")]
        public string Pattern = string.Empty;

        [XmlAttribute("ignoreCase")]
        public bool IgnoreCase = true;

        [XmlAttribute("repeats")]
        public int Repeats;

        [XmlAttribute("group")]
        public int Group;

        [XmlAttribute("capture")]
        public int Capture;

        [XmlAttribute("filter")]
        public string Filter = string.Empty;

        [XmlArray("replace")]
        [XmlArrayItem("filter", typeof(ReplaceType))]
        public ArrayList Replaces = new ArrayList();

        [XmlAttribute("url")]
        public string Url = string.Empty;

        [XmlAttribute("urlextension")]
        public string UrlExtension = string.Empty;

        [XmlAttribute("pages")]
        public string Pages = string.Empty;

        [XmlAttribute("splits")]
        public string Splits = string.Empty;

        [XmlAttribute("splitBefore")]
        public string SplitBefore = string.Empty;

        [XmlAttribute("exchange")]
        public string Exchange = string.Empty;

        [XmlAttribute("commentAuthor")]
        public string CommentAuthor = string.Empty;

        [XmlAttribute("commentContent")]
        public string CommentContent = string.Empty;

        [XmlAttribute("commentDate")]
        public string CommentDate = string.Empty;


        [XmlAttribute("dateformat")]
        public string DateFormat = string.Empty;

        [XmlAttribute("compareDateType")]
        public string CompareDateType = string.Empty;

        public ArrayList ParseData(XmlNode node)
        {
            ArrayList list = ParseByContext(node);
            //will parse by pattern if the context string is empty
            if (list.Count == 0)
                list.Add(node.InnerXml);
            list = ParseByPattern(list);
            return list;
        }

        public string GetString(XmlNode mainNode)
        {
            return GetString(mainNode, null);
        }

        public XmlNode GetXmlNode(XmlNode mainNode, XmlNamespaceManager nsManager)
        {
            if (mainNode == null || string.IsNullOrEmpty(mainNode.InnerText))
                return null;

            XmlNode node = null;
            if (Context != string.Empty)
            {
                if (nsManager == null)
                    node = mainNode.SelectSingleNode(Context);
                else
                    node = mainNode.SelectSingleNode(Context, nsManager);
            }

            GC.Collect();

            return node;
        }

        public string GetHtmlString(XmlNode mainNode, XmlNamespaceManager nsManager)
        {
            if (mainNode == null || string.IsNullOrEmpty(mainNode.InnerText))
                return "";

            string ret;

            if (Context != string.Empty)
            {
                XmlNode node;
                if (nsManager == null)
                    node = mainNode.SelectSingleNode(Context);
                else
                    node = mainNode.SelectSingleNode(Context, nsManager);
                if (node != null)
                {
                    if (node is XmlElement)
                    {
                        try
                        {
                            ret = node.OuterXml;
                        }
                        catch (Exception)
                        {
                            ret = node.InnerText;
                        }
                    }
                    else
                        ret = node.Value;
                }
                else
                    ret = string.Empty;
            }
            else
                ret = mainNode.OuterXml;

            ret = ret.Replace("&amp;", "&");
            ret = ret.Replace("&nbsp;", " ");
            GC.Collect();
            return ret.Trim();
        }


        public string GetString(XmlNode mainNode, XmlNamespaceManager nsManager)
        {
            if (mainNode == null || string.IsNullOrEmpty(mainNode.InnerText))
                return "";

            string ret;

            if (Context != string.Empty)
            {
                XmlNode node;
                if (nsManager == null)
                    node = mainNode.SelectSingleNode(Context);
                else
                    node = mainNode.SelectSingleNode(Context, nsManager);
                if (node != null)
                {
                    if (node is XmlElement)
                    {
                        try
                        {
                            ret = node.InnerXml;
                        }
                        catch (Exception)
                        {
                            ret = node.InnerText;
                        }
                    }
                    else
                        ret = node.Value;
                }
                else
                    ret = string.Empty;
            }
            else
                ret = mainNode.InnerXml;

            ret = BuildString(ret);
            ret = ret.Replace("&amp;", "&");
            ret = ret.Replace("&nbsp;", " ");
            GC.Collect();
            return ret.Trim();
        }

        private string RemoveUnicodeCharacter(string input)
        {
            var clone = input.Clone().ToString();

            string[] a = { "a", "á", "ả", "ã", "ạ", "à", "ă", "ắ", "ẳ", "ẵ", "ặ", "ằ", "â", "ấ", "ẩ", "ẫ", "ậ", "ầ" };
            string[] u = { "u", "ú", "ủ", "ũ", "ụ", "ù", "ư", "ứ", "ử", "ữ", "ự", "ừ" };
            string[] o = { "o", "ó", "ỏ", "õ", "ọ", "ò", "ô", "ố", "ổ", "ỗ", "ộ", "ồ", "ơ", "ớ", "ở", "ỡ", "ợ", "ờ" };
            string[] i = { "i", "í", "ỉ", "ĩ", "ị", "ì" };
            string[] y = { "y", "ý", "ỷ", "ỹ", "ỵ", "ỳ" };
            string[] e = { "e", "é", "ẻ", "ẽ", "ẹ", "è", "ê", "ế", "ể", "ễ", "ệ", "ề" };
            string[] d = { "d", "đ" };

            string[][] unicodes = { a, u, o, i, y, e, d };

            foreach (var array in unicodes)
            {
                foreach (var c in array)
                    if (clone.Contains(c))
                        clone = clone.Replace(c, array.First());
            }

            return clone;
        }

        public string BuildString(string ret)
        {
            RegexOptions flag = RegexOptions.None;
            if (IgnoreCase)
                flag |= RegexOptions.IgnoreCase;

            if (Pattern != string.Empty)
            {
                var regex = new Regex(Pattern, flag);
                Match match = regex.Match(ret.Replace("\r", "").Replace("\n", ""));
                ret = match.Groups.Count > 0 ? match.Groups[1].Value : string.Empty;
            }

            if (Replaces != null)
            {
                string replaceString;
                CSE.CsEval.EvalEnvironment = this;

                foreach (ReplaceType replaceType in Replaces)
                {
                    replaceString = replaceType.Replace;
                    //execute C# code to replace
                    if (replaceType.IsExpression)
                        replaceString = CSE.CsEval.Eval(replaceType.Replace).ToString();

                    var regex = new Regex(replaceType.Original, flag);

                    if (replaceType.IsEval && regex.Match(ret).Success)
                    {

                        ret = regex.Replace(ret, replaceString);
                        ret = RemoveUnicodeCharacter(ret);
                        ret = CSE.CsEval.Eval(ret).ToString();
                    }
                    else
                        ret = regex.Replace(ret, replaceString);

                }
            }
            return ret;
        }

        private ArrayList ParseByContext(XmlNode mainNode)
        {
            var list = new ArrayList();
            if (Context == string.Empty)
                return list;

            XmlNodeList nodeList = mainNode.SelectNodes(Context);
            foreach (XmlNode node in nodeList)
            {
                list.Add(node.InnerXml);
            }

            return list;
        }

        private ArrayList ParseByPattern(ArrayList list)
        {
            if (Pattern == string.Empty)
                return list;
            //set flag for Regular Expression
            RegexOptions flag = RegexOptions.None;
            if (IgnoreCase)
                flag |= RegexOptions.IgnoreCase;
            var regex = new Regex(Pattern, flag);
            MatchCollection mc;
            var returnList = new ArrayList();
            foreach (string data in list)
            {
                mc = regex.Matches(data);
                for (int i = 0; i < mc.Count; i++)
                {
                    returnList.Add(mc[i].Groups[1].Value);
                }
            }

            return returnList;
        }

        public string ParseByPattern(string value)
        {
            if (Pattern == string.Empty)
                return value;
            //set flag for Regular Expression
            RegexOptions flag = RegexOptions.None;
            if (IgnoreCase)
                flag |= RegexOptions.IgnoreCase;
            Regex regex = new Regex(Pattern, flag);
            Match match = regex.Match(value);

            return match.Groups[1].Value;
        }
    }
}
